24. 两两交换链表中的节点

24. 两两交换链表中的节点

分析

交换链表中的两个点,实际上涉及到四个点

即,我们要交换 AB 两个节点,实际上涉及到 前、A、B、后四个节点,其中要求改的为 前、A、B 三个节点。
而 AB 这两个节点其实也可以通过最前面那个节点的 next 指针访问到,于是思路就有了,用 while 循环,一次循环交换两个节点,交换完成后往后走两个节点,如果后面不足两个节点,就跳出来,这就是大概的思路。
在循环中设置下一此交换的头结点的时候,很容易搞错,因为节点的指针已经更换了,一个万无一失的办法就是从当前循环的 nowNode 通过 next 来访问 nowNode.next.next

解题

public ListNode swapPairs(ListNode head) {
    ListNode dummyHead = new ListNode(-1,head);
    ListNode nowNode = dummyHead;
    while(true){
        ListNode nextNode = nowNode.next;
        if(nextNode==null){
            break;
        }
        ListNode nextNextNode = nextNode.next;
        if(nextNextNode==null){
            break;
        }
        // 交换之前,先把nextNextNode的下一个节点找到
        ListNode finalNode = nextNextNode.next;
        // 开始交换
        nowNode.next = nextNextNode;
        nextNextNode.next = nextNode;
        nextNode.next = finalNode;
        // 更新当前节点,这个地方很容易搞错,因为节点的位置已经更换了,
        // 一个万无一失的办法就是从 nowNode 通过 next 来访问。
        nowNode = nowNode.next.next;
    }
    return dummyHead.next;
}

更高级的方法,用递归,递归的思路先交换后面的,再交换前面的,交换完后面的,其结果再参与到前面的交换中。非常短小精妙,当然写起来也更容易写错。哈哈哈

private static ListNode swapPairs1(ListNode head) {  
    if (head == null || head.next == null) {  
        return head;  
    }  
    // 调用swapPairs1的返回结果恰恰跟返回newHead连接上了,简短,精妙  
    ListNode nextPair = swapPairs1(head.next.next);  
    head.next.next = head;  
    head.next = nextPair;  
    return head.next;  
}

相关题